package com.example.spring_demo.di;

import com.example.spring_demo.config.UserInfo;
import com.example.spring_demo.service.TestService;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

/**
 * @className: TestController
 * @author: 芃
 * @description:
 * @date: 2024/12/23 14:39
 */
@Controller
public class TestController {

    //@Autowired 和 @Resource注解的区别
    // 1、@Autowired注解由Spring提供 @Resource注解由JDK提供
    // 2、@Autowired注解默认按照byType（根据bean类型）自动注入，而@Resource注解默认按照byName（根据bean名称）自动注入
    // @Autowired默认是按照类型注入的，如果同一个类型存在多个bean，则会按照名称匹配，如果名称匹配不上，则会报错。


    //属性注入
    // 属性注入以类型进行匹配，与注入的属性名称无关
    // 但是如果一个类型存在多个对象时，优先名称匹配，如果名称匹配不上，那就报错了
    // ※ 无法注入一个Final修饰的属性->解决：定义时进行赋值、构造方法中进行赋值
    // 如何规避上述问题？
    // 1. 使用@Autowired注解，可以自动匹配到对应的bean对象
    // 2. 使用@Qualifier注解，可以指定bean的名称进行匹配
    // 3. 使用@Resource注解，可以指定bean的名称进行匹配，但是不推荐使用，因为它不支持@Autowired注解的功能
    @Autowired
    @Qualifier("testService") // -> @Resource(name="testService")
    private TestService testService;

    public void doTestController(){
        testService.doTestService();
    }

    //构造方法注入
    /*
     * 当无参构造和有参构造同时存在时，默认调用无参构造
     * 当存在多个有参构造时，需要使用@Autowired注解告知默认采用哪个构造方法进行注入
     */
    private TestService testService2;
    @Getter
    private UserInfo userInfo;

    @Autowired
    public TestController(TestService testService2) {
        this.testService2 = testService2;
    }

    public TestController(TestService testService2, UserInfo userInfo) {
        this.userInfo = userInfo;
        this.testService2 = testService2;
    }

    public void doTestController2(){
        testService2.doTestService();
    }

    //Setter方法注入
    private TestService testService3;

    @Autowired
    public void setTestService3(TestService testService3) {
        this.testService3 = testService3;
    }

    public void doTestController3() {
        testService3.doTestService();
    }
}
